package com.file.parser;

import com.file.bo.ResponseData;
import com.file.bo.WebankAsset;
import com.file.bo.WebankAssetInfo;
import com.file.constant.ErrorCode;
import com.file.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import technology.tabula.*;
import technology.tabula.detectors.SpreadsheetDetectionAlgorithm;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;

import java.io.File;
import java.util.*;

/**
 * 微众银行理财类资产证明解析
 * @author anyspa
 */

@Slf4j
public class WebankAssetPdfParser extends BasePdfParser {

    public ResponseData<String> parseWebankAssetPdfToJson(String daId, String filePath) {
        log.info("parseWebankAssetPdfToJson started, daId:{}", daId);
        String json = null;

        try {
            WebankAsset webankAsset = parseWebankAssetPdf(filePath);
            json = JsonUtils.convertObjectToJson(webankAsset);
        } catch (Exception e) {
            log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseWebankAssetPdfToJson failed", e);
            return new ResponseData<>(json, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
        }

        log.info("parseWebankAssetPdfToJson completed, daId:{}", daId);
        return new ResponseData<>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
    }

    private WebankAsset parseWebankAssetPdf(String filePath) {
        WebankAsset webankAsset = parseWebankAssetHeader(filePath);

        parseWebankAssetDetail(filePath, webankAsset);

        return webankAsset;
    }

    private WebankAsset parseWebankAssetHeader(String filePath) {
        WebankAsset webankAsset = new WebankAsset();
        String headerText = parsePdfHeaderText(filePath);
        String number = headerText.substring(headerText.indexOf("编号：") + 3, headerText.indexOf("NO："));
        String name = headerText.substring(headerText.indexOf("兹证明") + 3, headerText.indexOf("先生/女士")).trim();
        String idNo = headerText.substring(headerText.indexOf("身份证件号码：") + 7, headerText.indexOf("We hereby"));
        if (idNo.contains("）")) {
            idNo = idNo.substring(idNo.indexOf("）") + 1);
        }
        String year = headerText.substring(headerText.indexOf("Up to") + 5, headerText.indexOf("Year")).trim();
        year = year.replaceAll("\\s+", StringUtils.EMPTY);
        String mouth = headerText.substring(headerText.indexOf("Year") + 4, headerText.indexOf("Month")).trim();
        mouth = mouth.replaceAll("\\s+", StringUtils.EMPTY);
        String date = headerText.substring(headerText.indexOf("Month") + 5, headerText.indexOf("Date")).trim();
        date = date.replaceAll("\\s+", StringUtils.EMPTY);
        String hour = headerText.substring(headerText.indexOf("Date") + 5, headerText.indexOf("Hour")).trim();
        hour = hour.replaceAll("\\s+", StringUtils.EMPTY);
        String expirationDate = year.concat("年").concat(mouth).concat("月").concat(date).concat("日").concat(hour).concat("时");
        String assetTotal = headerText.substring(headerText.indexOf("资产明细情况如下：") + 9, headerText.indexOf("amount of"));
        webankAsset.setNumber(number);
        webankAsset.setName(name.replaceAll("\\s+", StringUtils.EMPTY));
        webankAsset.setIdNo(idNo);
        webankAsset.setExpirationDate(expirationDate);
        webankAsset.setAssetTotal(assetTotal);

        String footerText = parsePdfPageTextByPageNumber(filePath, getPdfPageNumber(filePath));
        String issueDate = footerText.substring(footerText.lastIndexOf("日期：") + 3, footerText.lastIndexOf("Seal of WeBank"));
        webankAsset.setIssueDate(issueDate);
        return webankAsset;
    }

    private void parseWebankAssetDetail(String filePath, WebankAsset webankAsset) {
        List<WebankAssetInfo> webankAssetInfos = new ArrayList<>();
        // 1. 读取文件
        File pdf = new File(filePath);

        // 2. pdfbox读取PDDocument
        try (PDDocument pdfDocument = PDDocument.load(pdf)) {

            // 3. tabula新建ObjectExtractor和NurminenDetectionAlgorithm，同时准备接收表格Rectangle的结构
            ObjectExtractor objectExtractor = new ObjectExtractor(pdfDocument);
            SpreadsheetDetectionAlgorithm sea = new SpreadsheetDetectionAlgorithm();

            Map<Integer, List<Rectangle>> detectedTables = new HashMap<>();

            // 4. 获取每页的PageIterator
            PageIterator pages = objectExtractor.extract();

            // 5. 解析每页的Rectangle(table的位置)
            while (pages.hasNext()) {
                Page page = pages.next();
                List<Rectangle> tablesOnPage = sea.detect(page);
                if (tablesOnPage.size() > 0) {
                    detectedTables.put(page.getPageNumber(), tablesOnPage);
                }
            }

            // 6.通过table位置获取表格具体内容
            SpreadsheetExtractionAlgorithm bea = new SpreadsheetExtractionAlgorithm();

            // 如果单页pdf中有多个表格，则解析出来的List<Rectangle>会有多个对象
            for (Map.Entry<Integer, List<Rectangle>> entry : detectedTables.entrySet()) {
                Page page = objectExtractor.extract(entry.getKey());

                // 默认每页只有一个表格，因此获取第0个rectangle
                Rectangle rectangle = entry.getValue().get(0);
                Page area = page.getArea(rectangle.getTop(), rectangle.getLeft(), rectangle.getBottom(), rectangle.getRight());

                List<Table> tableList = bea.extract(area);

                // 默认每页只有一个表格，因此获取第0个table
                Table table = tableList.get(0);

                for (int i = 0; i < table.getRowCount(); i++) {
                    if (Objects.nonNull(table.getCell(i, 0).getText())) {
                        if (table.getCell(i, 0).getText().contains("资产种类")
                                || table.getCell(i, 0).getText().contains("Types of Assets")) {
                            continue;
                        }
                        WebankAssetInfo webankAssetInfo = getWebankAssetInfoByTable(table, i);
                        if (StringUtils.equals(webankAssetInfo.getAssetType(), "/")) {
                            continue;
                        }
                        webankAssetInfos.add(webankAssetInfo);
                    }
                }
            }
            webankAsset.setWebankAssetInfos(webankAssetInfos);
        }  catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private WebankAssetInfo getWebankAssetInfoByTable(Table table, int i) {
        WebankAssetInfo webankAssetInfo = new WebankAssetInfo();
        webankAssetInfo.setAssetType(table.getCell(i, 0).getText(false));
        webankAssetInfo.setCurrency(table.getCell(i, 1).getText(false));
        webankAssetInfo.setValueDate(table.getCell(i, 2).getText(false));
        webankAssetInfo.setDueDate(table.getCell(i, 3).getText(false));
        return webankAssetInfo;
    }

    public static void main(String[] args) {
        WebankAssetPdfParser webankAssetParser = new WebankAssetPdfParser();
        String json = webankAssetParser.parseWebankAssetPdfToJson("", "D:\\data\\file\\webank\\个人资产证明No.Z202301130062-1.pdf").getData();
        System.out.println(json);
    }
}
